--------------Math and Me--------------
A 4am crack                  2015-11-03
---------------------------------------

Name: Math and Me
Version: 1.6
Genre: educational
Year: 1988
Publisher: Davidson & Associates, Inc.
Media: 3.5-inch floppy (800K)
OS: ProDOS 1.4
Other versions: Asimov archive has an
  uncredited crack
Similar cracks:
  #484 Spell It Plus (3.5")
  #481 Math Blaster Mystery 1.3 (3.5")
  #457 Math Blaster Mystery 1.3 (5.25")
  #200 Math Blaster Mystery 1.0 (5.25")
  #166 Word Attack Plus French (5.25")
  #165 Alge-Blaster Plus (5.25")

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


Copy ][+ 9.1 ("COPY" > "DISK")
  read error on block $0308; copy loads
  ProDOS then quits to program selector

CFFA 3000 import
  read error on block 776 (= $0308);
  booting the disk image in an emulator
  exhibits the same behavior as the
  backup I made with Copy ][+ disk copy
  (boots ProDOS then quits via a "Quit"
  MLI call)

It's a very ProDOS-y way of saying
"f--- you."

The original disk boots without
complaint, so either this bad block is
part of the protection check, or it's
unrelated and I got incredibly lucky.

Next steps:

  1. Trace the startup program
  2. Find and disable the protection
     check
  3. Declare victory(*)

(*) Take a nap

                   ~

               Chapter 1
       FORTH? In *My* Apple II?
    It's More Likely Than You Think


[S7,D1=my ProDOS hard drive]
[S5,D1=non-working copy]

]PR#7
...
]CAT,S5,D1

/MM1.60

 NAME           TYPE  BLOCKS  MODIFIED

 FINDER.DATA     $C9       3  18-AUG-88
 DUMP.HIRES.R    BIN       5   7-MAY-87
 CTEXT.LIST      TXT       1  16-AUG-88
 ENTRY.PAK       TXT       7  18-AUG-88
 INTER.DRIVERS   TXT       5   4-AUG-87
 PRINTER.DRIVERS TXT      12  18-MAY-87
 TEXT.LIST       TXT       3  16-AUG-88
 REBOOT          BIN       1  25-FEB-88
 AFORTH          BIN      67  16-AUG-88
 PRODOS          SYS      32  17-APR-87
 JRDUMP.OVL      TXT       7  16-AUG-88
 FINDER.ROOT     $C9       1  18-AUG-88
 DESKTOP         $00       3  16-SEP-56
 JR.SYSTEM       SYS       4   7-APR-88
 TRIANGLES.LIST  TXT      17  13-JUL-87
 ADDITION.PAK    TXT       7   9-SEP-87
 MONKEYG.PAK     TXT       5   9-SEP-87
 MONKEYG.LIST    TXT      13   9-SEP-87
 NEW.FONT        BIN       7  23-MAR-88
 LARGE.LIST      TXT       6  22-JUL-87
 SMALL.LIST      TXT       7  14-JUL-87
 MSTRETCH.LIST   TXT       6  15-JUN-87
 RECTANGLES.LIST TXT      15  14-JUL-87
 CIRCLES.LIST    TXT      15  24-JUN-87
 FACES.LIST      TXT       4   7-JUL-87
 WLIFTER.GX      TXT      24  31-AUG-87
 THREE5.LST      TXT       1  31-MAR-88
 BANDL.LIST      TXT       9   7-JUN-88
 HOTAIR.PAK      TXT      12   9-SEP-87
 PATTERNS.PAK    TXT       6   9-SEP-87
 NUMBERS.PAK     TXT       6   9-SEP-87
 SHAPES.PAK      TXT       6   9-SEP-87
 MAIN.PAK        TXT       9   9-SEP-87
 SKATING.PAK     TXT      13   9-SEP-87
 MEDIUM.LIST     TXT       6  18-JUN-87
 SQUARES.LIST    TXT      14  13-JUL-87
 LARGE.FONT      TXT      10   9-SEP-87
 HOTAIR.LIST     TXT      16   4-SEP-87
 SOUND.ICON      TXT      11  17-AUG-87
 PRINTER.DATA    TXT       1  12-AUG-88
 TK.ABS          BIN      22  18-JUN-87

BLOCKS FREE: 1173     BLOCKS USED:  427

ProDOS always loads the first .SYSTEM
file at $2000 and jumps to it.

]PREFIX /MM1.60
]BLOAD JR.SYSTEM,A$2000,TSYS
]CALL -151

*2000L

2000-   20 D2 25    JSR   $25D2
2003-   4C 74 08    JMP   $0874

There's nothing loaded at $0874 yet, so
the subroutine at $25D2 must load
something from disk or copy something
from memory.

*25D2L

; straightforward memory relocation
25D2-   A2 00       LDX   #$00
25D4-   BD 03 20    LDA   $2003,X
25D7-   9D 01 08    STA   $0801,X
25DA-   BD 03 21    LDA   $2103,X
25DD-   9D 01 09    STA   $0901,X
25E0-   BD 03 22    LDA   $2203,X
25E3-   9D 01 0A    STA   $0A01,X
25E6-   BD 03 23    LDA   $2303,X
25E9-   9D 01 0B    STA   $0B01,X
25EC-   BD 03 24    LDA   $2403,X
25EF-   9D 01 0C    STA   $0C01,X
25F2-   BD 03 25    LDA   $2503,X
25F5-   E8          INX
25F6-   D0 DC       BNE   $25D4
25F8-   60          RTS

That's harmless enough. Let's run it.

*25D2G

*874L

0874-   20 C8 0A    JSR   $0AC8
0877-   F0 D9       BEQ   $0852

*852L

; read and write main memory
0852-   8E 04 C0    STX   $C004
0855-   8E 02 C0    STX   $C002

; call the quit handler (command $65)
0858-   20 00 BF    JSR   $BF00
085B-  [65 5E 08 04 00 00 00 00]

...which explains the behavior I saw on
my non-working copy.

*AC8L

; $BF30 is the last used slot and drive
; in "DSSS0000" format ("Beneath Apple
; ProDOS", p. 8-6)
0AC8-   AD 30 BF    LDA   $BF30
0ACB-   4A          LSR
0ACC-   4A          LSR
0ACD-   4A          LSR
0ACE-   4A          LSR
0ACF-   29 07       AND   #$07
0AD1-   09 C0       ORA   #$C0

; slot number munged into the high byte
; of the drive slot ROM, e.g. $C6
0AD3-   85 61       STA   $61
0AD5-   A9 00       LDA   #$00
0AD7-   85 60       STA   $60

; now look at some signature bytes in
; the peripheral ROM for the boot slot
; to determine what kind of floppy
; disk we booted from (5.25" or 3.5")
0AD9-   A0 01       LDY   #$01
0ADB-   B1 60       LDA   ($60),Y
0ADD-   C9 20       CMP   #$20
0ADF-   D0 22       BNE   $0B03
0AE1-   A0 03       LDY   #$03
0AE3-   B1 60       LDA   ($60),Y
0AE5-   D0 1C       BNE   $0B03
0AE7-   A0 05       LDY   #$05
0AE9-   B1 60       LDA   ($60),Y
0AEB-   C9 03       CMP   #$03
0AED-   D0 14       BNE   $0B03
0AEF-   A0 FF       LDY   #$FF
0AF1-   B1 60       LDA   ($60),Y
0AF3-   D0 0E       BNE   $0B03

; if 5.25-inch, use block $110 (which
; is somewhere on track $22)
0AF5-   A9 10       LDA   #$10
0AF7-   8D CE 0D    STA   $0DCE
0AFA-   A9 01       LDA   #$01
0AFC-   8D CF 0D    STA   $0DCF
0AFF-   D0 0C       BNE   $0B0D
0B01-   F0 0A       BEQ   $0B0D

; if 3.5-inch, use block $308 (this is
; the block I couldn't read when I
; tried to copy the disk)
0B03-   A9 08       LDA   #$08
0B05-   8D CE 0D    STA   $0DCE
0B08-   A9 03       LDA   #$03
0B0A-   8D CF 0D    STA   $0DCF

; fill out the rest of an MLI parameter
; table
0B0D-   AD 30 BF    LDA   $BF30
0B10-   8D CB 0D    STA   $0DCB
0B13-   A9 03       LDA   #$03
0B15-   8D CA 0D    STA   $0DCA
0B18-   A9 CA       LDA   #$CA
0B1A-   8D CC 0D    STA   $0DCC
0B1D-   A9 0B       LDA   #$0B
0B1F-   8D CD 0D    STA   $0DCD

; call MLI to read the specified block
; from disk (the $80 byte following the
; JSR is the READ_BLOCK command, and
; following that is the address of the
; MLI parameter table, $0DCA)
0B22-   20 00 BF    JSR   $BF00
0B25-  [80 CA 0D]

; if there was NOT a disk read error,
; then branch
0B28-   90 09       BCC   $0B33

; if there was any error other than an
; I/O error ($27), then branch
0B2A-   C9 27       CMP   #$27
0B2C-   D0 05       BNE   $0B33

; success path falls through to here --
; set a flag in zero page
0B2E-   A9 FF       LDA   #$FF
0B30-   85 FF       STA   $FF
0B32-   60          RTS

; failure path is here
0B33-   A9 00       LDA   #$00
0B35-   85 FF       STA   $FF
0B37-   60          RTS

This is definitely a form of copy
protection. It relies on a specific
sector being unreadable, and fails if
it's actually readable. Fun fact(*): it
is written so it can be re-used for
5.25-inch and 3.5-inch floppies. Since
my copy didn't reproduce the badness of
block $308, the MLI read routine
unexpectedly succeeds, and the program
knows it's been copied.

(*) not guaranteed, actual fun may vary

To bypass the protection, I can change
the failure path at $0B33 so it sets
the magic zero page flag to $FF instead
of $00 (just like the success path).

Block Warden
  ["C"hange device -> S5,D1]
  ["E"dit mode]
  [<Ctrl-S>earch]
    ["$20 00 BF 80"]

That will find the READ_BLOCK MLI call,
which is very close to the failure path
that I want to change.

Block $00A7,offset $136 change 00 to FF

Continuing the search, Block Warden
finds another match later. The code is
identical to what I saw in JR.SYSTEM.

Block $00DB,offset $136 change 00 to FF

]PR#5
...works...

Quod erat liberandum.

---------------------------------------
A 4am crack                     No. 485
------------------EOF------------------
